##################################################################
# File : /lua/ui/game/tooltip.lua
# Description : Tool Tips
# Author : GPG
##################################################################

local UIUtil = import('/lua/ui/uiutil.lua')
local Group = import('/lua/maui/group.lua').Group
local Text = import('/lua/maui/text.lua')
local Bitmap = import('/lua/maui/bitmap.lua').Bitmap
local LayoutHelpers = import('/lua/maui/layouthelpers.lua')
local TooltipInfo = import('/lua/ui/help/tooltips.lua')
local Prefs = import('/lua/user/prefs.lua')
local Button = import('/lua/maui/button.lua').Button
local Edit = import('/lua/maui/edit.lua').Edit
local Checkbox = import('/lua/maui/checkbox.lua').Checkbox
local Keymapping = import('/lua/keymap/DefaultKeyMap.lua').defaultKeyMap
local InGameUI = import('/lua/ui/game/InGameUI.lua')

local mouseoverDisplay = false
local createThread = false
local padding = 5
local tooltipFont = 'Arial'
local boldFont = 'Arial Black'


function DestroyMouseoverDisplay()
    if createThread then
        KillThread(createThread)
    end
    if mouseoverDisplay then
        mouseoverDisplay:Destroy()
        mouseoverDisplay = false
    end
end

################################
# Used by items in a shop
################################
function CreateItemTooltip(parent, itemInfo, cost)
    local textGroup = {}
    
    if itemInfo.DisplayName then
        textGroup.ItemName = LOC(itemInfo.DisplayName)
    end
    if cost then
        textGroup.ItemCost = cost
    end
    if itemInfo.Description then
        textGroup.Use = LOC(itemInfo.Description)
    end
    if itemInfo.Tooltip.ChanceOnHit then
        textGroup.ChanceOnHit = LOC(itemInfo.Tooltip.ChanceOnHit)
    end
    if itemInfo.Tooltip.Passives then
        textGroup.Passives = LOC(itemInfo.Tooltip.Passives)
    end
    if itemInfo.Tooltip.Auras then
        textGroup.Auras = LOC(itemInfo.Tooltip.Auras)
    end
    if itemInfo.Tooltip.Bonuses then
        textGroup.Bonuses = table.copy(itemInfo.Tooltip.Bonuses)
    end

    # Don't bother if we have tooltips disabled
    if not Prefs.GetOption('tooltips') then return end
    
    local tooltip = Group(parent)
    tooltip.Depth:Set(function() return parent.Depth() + 20000 end)
    tooltip.Width:Set(288)
    
    local imgtop = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_top.dds')
    imgtop.Width:Set(288)
    imgtop.Height:Set(28)
    LayoutHelpers.AtLeftTopIn(imgtop, tooltip)

    local imgmid = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_mid.dds')
    imgmid.Width:Set(288)
    imgmid.Height:Set(function() return tooltip.Height() - imgtop.Height() end)
    LayoutHelpers.AnchorToBottom(imgmid, imgtop)
    LayoutHelpers.AtLeftIn(imgmid, imgtop)
    
    local imgbtm = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_btm.dds')
    imgbtm.Width:Set(288)
    imgbtm.Height:Set(27)
    LayoutHelpers.AnchorToBottom(imgbtm, imgmid)
    LayoutHelpers.AtLeftIn(imgbtm, imgmid)
    
    local vertpadding = 2
    local horzpadding = 2
    local lineHeight = 16
    local lineWidth = tooltip.Width() - 40
    
    local tooltipHeight = 0
    
    ### Item name
    tooltip.title = UIUtil.CreateText(tooltip, textGroup.ItemName, 14, boldFont)
    tooltip.title:SetColor('ff0000ff')
    LayoutHelpers.AtLeftTopIn(tooltip.title, tooltip, 15, 15)
    
    ### Item cost
    tooltip.cost = UIUtil.CreateText(tooltip, textGroup.ItemCost, 14, tooltipFont)
    LayoutHelpers.AtTopIn(tooltip.cost, tooltip.title)
    LayoutHelpers.AtRightIn(tooltip.cost, tooltip, 15)
    
    tooltip.goldicon = Bitmap(tooltip, '/textures/ui/common/icons/gold.dds')
    tooltip.goldicon.Width:Set(20)
    tooltip.goldicon.Height:Set(20)
    LayoutHelpers.CenteredLeftOf(tooltip.goldicon, tooltip.cost, 1)
    
    tooltipHeight = tooltipHeight + lineHeight + vertpadding
    
    local lastline = tooltip.title
    local offset = 5   

    ### Item Use
    if textGroup.Use then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblUse = Text.WrapText(textGroup.Use, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()    
        
        for k, v in tmptblUse do
            local textctrl = UIUtil.CreateText(tooltip, tmptblUse[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('ff00ff00')
            lastline = textctrl 
            tooltipHeight = tooltipHeight + lineHeight + offset
            offset = 0
        end
    end
    
    ### Item Bonuses
    if textGroup.Bonuses then
        for k, v in textGroup.Bonuses do
            local textctrl = UIUtil.CreateText(tooltip, textGroup.Bonuses[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            lastline = textctrl 
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    ### Chance on Hit
    if textGroup.ChanceOnHit then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblCoH = Text.WrapText(textGroup.ChanceOnHit, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()     
        for k, v in tmptblCoH do
            local textctrl = UIUtil.CreateText(tooltip, tmptblCoH[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('ff00ff00')
            lastline = textctrl 
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    ### Passives
    if textGroup.Passives then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblPassives = Text.WrapText(textGroup.Passives, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()   
        for k, v in tmptblPassives do
            local textctrl = UIUtil.CreateText(tooltip, tmptblPassives[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('fffcff00')
            lastline = textctrl 
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    ### Auras
    if textGroup.Auras then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblAuras = Text.WrapText(textGroup.Auras, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()   
        for k, v in tmptblAuras do
            local textctrl = UIUtil.CreateText(tooltip, tmptblAuras[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('ff00ff00')
            lastline = textctrl 
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    tooltip.Height:Set( function() return tooltipHeight + vertpadding + vertpadding end)
    tooltip.Top:Set(0)
    tooltip.Left:Set(0)
    
    # Figure out where to display the tooltip
    local frame = GetFrame(0)   
    if frame.Height() - (parent.Top() + tooltip.Height()) > 0 then
        tooltip.Top:Set(function() return math.min(parent.Bottom() - parent.Height(), frame.Height() - tooltip.Height()) end )
        if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
            tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
        else
            tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
        end
    else
        tooltip.Top:Set(function() return parent.Bottom() - tooltip.Height() + 10 end )
        if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
            tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
        else
            tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
        end
    end  

    function tooltip.Destroy(self)
        Group.Destroy(self) 
    end
    
    # Handle tooltip delay
    if Prefs.GetOption('tooltip_delay') then
        local delay = Prefs.GetOption('tooltip_delay') or 0
        local alpha = 0
        local totalTime = 0
        
        tooltip:SetAlpha(alpha, true)
        tooltip:SetNeedsFrameUpdate(true)
        function tooltip.OnFrame(self, deltaTime)
            if totalTime > delay then
                if alpha < 1 then
                    self:SetAlpha(alpha, true)
                    alpha = alpha + (deltaTime * 4)
                else
                    self:SetAlpha(1, true)
                    self:SetNeedsFrameUpdate(false)
                end
            end
            totalTime = totalTime + deltaTime
        end
    end

    return tooltip    
end

################################
# Used by abilities in the HUD
################################
function CreateAbilityTooltip(parent, abilityData)
    local textGroup = {}
    
    # test data
    textGroup.Name = LOC(abilityData.DisplayName)
    textGroup.ManaCost = abilityData.EnergyCost
    textGroup.Cooldown = abilityData.Cooldown
    textGroup.Description = LOC(abilityData.Description) 
    
    if abilityData.CastingTime then
        #textGroup.CastTime = abilityData.CastingTime
        textGroup.CastTime = string.format("%.2f", abilityData.CastingTime)
    end
    
    # Don't bother if we have tooltips disabled
    if not Prefs.GetOption('tooltips') then return end
    
    local tooltip = Group(parent)
    tooltip.Depth:Set(function() return parent.Depth() + 20000 end)
    tooltip.Width:Set(288)
    
    local imgtop = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_top.dds')
    imgtop.Width:Set(288)
    imgtop.Height:Set(28)
    LayoutHelpers.AtLeftTopIn(imgtop, tooltip)

    local imgmid = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_mid.dds')
    imgmid.Width:Set(288)
    imgmid.Height:Set(function() return tooltip.Height() - imgtop.Height() end)
    LayoutHelpers.AnchorToBottom(imgmid, imgtop)
    LayoutHelpers.AtLeftIn(imgmid, imgtop)
    
    local imgbtm = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_btm.dds')
    imgbtm.Width:Set(288)
    imgbtm.Height:Set(27)
    LayoutHelpers.AnchorToBottom(imgbtm, imgmid)
    LayoutHelpers.AtLeftIn(imgbtm, imgmid)
    
    local vertpadding = 4
    local horzpadding = 2
    local lineHeight = 16
    local lineWidth = tooltip.Width() - 40
    
    local tooltipHeight = 0
    
    ### Item name
    tooltip.title = UIUtil.CreateText(tooltip, textGroup.Name, 14, boldFont)
    LayoutHelpers.AtLeftTopIn(tooltip.title, tooltip, 15, 15)
    tooltipHeight = tooltipHeight + lineHeight + vertpadding
    
    if abilityData.TargetAlliance == 'Enemy' then
        tooltip.title:SetColor('ffff0000')
    else
        tooltip.title:SetColor('ff00ff00')
    end
    
    local lastline = tooltip.title
    
    ### Item cost
    if textGroup.ManaCost then
        tooltip.mana = UIUtil.CreateText(tooltip, textGroup.ManaCost .. ' Mana', 14, tooltipFont)
        LayoutHelpers.Below(tooltip.mana, lastline)
        LayoutHelpers.AtLeftIn(tooltip.mana, lastline)
        tooltipHeight = tooltipHeight + lineHeight
        
        lastline = tooltip.mana
    end
    
    ### Cast Time
    if textGroup.CastTime then
        tooltip.castTime = UIUtil.CreateText(tooltip, textGroup.CastTime .. ' Seconds', 14, tooltipFont)
        LayoutHelpers.Below(tooltip.castTime, lastline)
        LayoutHelpers.AtLeftIn(tooltip.castTime, lastline)
        tooltipHeight = tooltipHeight + lineHeight
    
        lastline = tooltip.castTime
    else
        if not abilityData.Placeholder then
            tooltip.castTime = UIUtil.CreateText(tooltip, 'Instant', 14, tooltipFont)
            LayoutHelpers.Below(tooltip.castTime, lastline)
            LayoutHelpers.AtLeftIn(tooltip.castTime, lastline)
            tooltipHeight = tooltipHeight + lineHeight
    
            lastline = tooltip.castTime
        end
    end
    
    
    ### Cooldown Time
    if textGroup.Cooldown then
        tooltip.cooldown = UIUtil.CreateText(tooltip, textGroup.Cooldown .. ' second cooldown', 14, tooltipFont)
        LayoutHelpers.AtTopIn(tooltip.cooldown, lastline)
        LayoutHelpers.AtRightIn(tooltip.cooldown, tooltip, 15)
    end    
    
    local offset = 5
    
    ### Description
    if textGroup.Description then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblDesc = Text.WrapText(textGroup.Description, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()   
        for k, v in tmptblDesc do
            local textctrl = UIUtil.CreateText(tooltip, tmptblDesc[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('fffcff00')
            lastline = textctrl 
            offset = 0
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    tooltip.Height:Set( function() return tooltipHeight + vertpadding + vertpadding end)
    
    # Dock this tooltip in the lower right
    local hudframe = InGameUI.HUDParent
    tooltip.Bottom:Set(function() return hudframe.Top() + 5 end)
    tooltip.Right:Set(function() return GetFrame(0).Right() - 5 end)
    
    # On destroy
    function tooltip.Destroy(self)
        Group.Destroy(self) 
    end
    
    # Handle tooltip delay
    if Prefs.GetOption('tooltip_delay') then
        local delay = Prefs.GetOption('tooltip_delay') or 0
        local alpha = 0
        local totalTime = 0
        
        tooltip:SetAlpha(alpha, true)
        tooltip:SetNeedsFrameUpdate(true)
        function tooltip.OnFrame(self, deltaTime)
            if totalTime > delay then
                if alpha < 1 then
                    self:SetAlpha(alpha, true)
                    alpha = alpha + (deltaTime * 4)
                else
                    self:SetAlpha(1, true)
                    self:SetNeedsFrameUpdate(false)
                end
            end
            totalTime = totalTime + deltaTime
        end
    end

    return tooltip    
end

################################################################
# used by anything that creates a title/body on the fly
################################################################
function CreateExtendedTooltip(parent, title, body, docked)
    # Don't bother if we have tooltips disabled
    if not Prefs.GetOption('tooltips') then return end
    
    local tooltip = Group(parent)
    tooltip.Depth:Set(function() return parent.Depth() + 20000 end)
    tooltip.Width:Set(288)
    
    local imgtop = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_top.dds')
    imgtop.Width:Set(288)
    imgtop.Height:Set(28)
    LayoutHelpers.AtLeftTopIn(imgtop, tooltip)

    local imgmid = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_mid.dds')
    imgmid.Width:Set(288)
    imgmid.Height:Set(function() return tooltip.Height() - imgtop.Height() end)
    LayoutHelpers.AnchorToBottom(imgmid, imgtop)
    LayoutHelpers.AtLeftIn(imgmid, imgtop)
    
    local imgbtm = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_btm.dds')
    imgbtm.Width:Set(288)
    imgbtm.Height:Set(27)
    LayoutHelpers.AnchorToBottom(imgbtm, imgmid)
    LayoutHelpers.AtLeftIn(imgbtm, imgmid)
    
    local vertpadding = 5
    local horzpadding = 2
    local lineHeight = 16
    local lineWidth = tooltip.Width() - 40
    
    local tooltipHeight = 0
    
    ### Title
    tooltip.title = UIUtil.CreateText(tooltip, LOC(title), 14, boldFont)
    LayoutHelpers.AtLeftTopIn(tooltip.title, tooltip, 15, 15)
    tooltipHeight = tooltipHeight + lineHeight + vertpadding
    tooltip.title:SetColor('ff00ff00')
    
    local offset = 5
    local lastline = tooltip.title
    
    ### Body
    if body then
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblDesc = Text.WrapText(LOC(body), lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()   
        for k, v in tmptblDesc do
            local textctrl = UIUtil.CreateText(tooltip, tmptblDesc[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('fffcff00')
            lastline = textctrl 
            offset = 0
            tooltipHeight = tooltipHeight + lineHeight
        end
    end
    
    # On destroy
    function tooltip.Destroy(self)
        Group.Destroy(self) 
    end
    
    tooltip.Height:Set( function() return tooltipHeight + vertpadding + vertpadding end)
    
    # If docked is true, dock this tooltip in the lower right
    local frame = GetFrame(0)
    local hudframe = InGameUI.HUDParent
    
    if docked then
        tooltip.Bottom:Set(function() return hudframe.Top() + 5 end)
        tooltip.Right:Set(function() return GetFrame(0).Right() - 5 end)
    else
        if frame.Height() - (parent.Top() + tooltip.Height()) > 0 then
            tooltip.Top:Set(function() return math.min(parent.Bottom() - parent.Height(), frame.Height() - tooltip.Height()) end )
            if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
                tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
            else
                tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
            end
        else
            tooltip.Top:Set(function() return parent.Bottom() - tooltip.Height() + 10 end )
            if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
                tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
            else
                tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
            end
        end 
    end
    
    # Handle tooltip delay
    if Prefs.GetOption('tooltip_delay') then
        local delay = Prefs.GetOption('tooltip_delay') or 0
        local alpha = 0
        local totalTime = 0
        
        tooltip:SetAlpha(alpha, true)
        tooltip:SetNeedsFrameUpdate(true)
        function tooltip.OnFrame(self, deltaTime)
            if totalTime > delay then
                if alpha < 1 then
                    self:SetAlpha(alpha, true)
                    alpha = alpha + (deltaTime * 4)
                else
                    self:SetAlpha(1, true)
                    self:SetNeedsFrameUpdate(false)
                end
            end
            totalTime = totalTime + deltaTime
        end
    end
    
    return tooltip   
end

#####################################################################
# used by elements that have a defined tooltip in help/tooltips.lua
#####################################################################
function CreateGenericTooltip(parent, tooltipID, docked)
    # Don't bother if we have tooltips disabled
    if not Prefs.GetOption('tooltips') then return end
    
    local tooltip = Group(parent)
    tooltip.Depth:Set(function() return parent.Depth() + 20000 end)
    tooltip.Width:Set(288)
    
    local imgtop = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_top.dds')
    imgtop.Width:Set(288)
    imgtop.Height:Set(28)
    LayoutHelpers.AtLeftTopIn(imgtop, tooltip)

    local imgmid = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_mid.dds')
    imgmid.Width:Set(288)
    imgmid.Height:Set(function() return tooltip.Height() - imgtop.Height() end)
    LayoutHelpers.AnchorToBottom(imgmid, imgtop)
    LayoutHelpers.AtLeftIn(imgmid, imgtop)
    
    local imgbtm = Bitmap(tooltip, '/textures/ui/common/tooltips/tooltip_btm.dds')
    imgbtm.Width:Set(288)
    imgbtm.Height:Set(27)
    LayoutHelpers.AnchorToBottom(imgbtm, imgmid)
    LayoutHelpers.AtLeftIn(imgbtm, imgmid)
    
    local vertpadding = 5
    local horzpadding = 2
    local lineHeight = 16
    local lineWidth = tooltip.Width() - 40
    
    local tooltipHeight = 0
    
    if tooltipID then
        local title = LOC(TooltipInfo.Tooltips[tooltipID].title)
        local body = LOC(TooltipInfo.Tooltips[tooltipID].description)
        local keyId = LOC(TooltipInfo.Tooltips[tooltipID].keyID)
        local title_concat = title
        
        if keyId and keyId != '' then
            for k, v in Keymapping do
                if v == keyId then
                    local properkeyname = import('/lua/ui/game/keybindings.lua').formatkeyname(k)
                    title_concat = LOCF("%s (%s)", title, properkeyname)
                    break
                end
            end
        end
        
        ### Title
        tooltip.title = UIUtil.CreateText(tooltip, title_concat, 14, boldFont)
        LayoutHelpers.AtLeftTopIn(tooltip.title, tooltip, 15, 15)
        tooltipHeight = tooltipHeight + lineHeight + vertpadding
        tooltip.title:SetColor('ff00ff00')
        
        local offset = 5
        local lastline = tooltip.title
        
        ### Body
        local tmp = UIUtil.CreateText(tooltip, '', 14, tooltipFont)
        local tmptblDesc = Text.WrapText(body, lineWidth, function(text) return tmp:GetStringAdvance(text) end)
        tmp:Destroy()   
        for k, v in tmptblDesc do
            local textctrl = UIUtil.CreateText(tooltip, tmptblDesc[k], 14, tooltipFont)
            
            LayoutHelpers.Below(textctrl, lastline, offset)
            LayoutHelpers.AtLeftIn(textctrl, lastline) 
            textctrl:SetColor('fffcff00')
            lastline = textctrl 
            offset = 0
            tooltipHeight = tooltipHeight + lineHeight
        end
    end

    # On destroy
    function tooltip.Destroy(self)
        Group.Destroy(self) 
    end
    
    tooltip.Height:Set( function() return tooltipHeight + vertpadding + vertpadding end)
    
    # If docked is true, dock this tooltip in the lower right
    local hudframe = InGameUI.HUDParent
    local frame = GetFrame(0)
    if docked then
        tooltip.Bottom:Set(function() return hudframe.Top() + 5 end)
        tooltip.Right:Set(function() return GetFrame(0).Right() - 5 end)
    else
        if frame.Height() - (parent.Top() + tooltip.Height()) > 0 then
            tooltip.Top:Set(function() return math.min(parent.Bottom() - parent.Height(), frame.Height() - tooltip.Height()) end )
            if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
                tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
            else
                tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
            end
        else
            tooltip.Top:Set(function() return parent.Bottom() - tooltip.Height() + 10 end )
            if frame.Width() - (parent.Right() + tooltip.Width()) > 0 then
                tooltip.Left:Set( function() return math.min(parent.Left() + parent.Width(), frame.Right() - tooltip.Width()) end )
            else
                tooltip.Left:Set( function() return parent.Left() - tooltip.Width() + 10 end )
            end
        end 
    end
    
    # Handle tooltip delay
    if Prefs.GetOption('tooltip_delay') then
        local delay = Prefs.GetOption('tooltip_delay') or 0
        local alpha = 0
        local totalTime = 0
        
        tooltip:SetAlpha(alpha, true)
        tooltip:SetNeedsFrameUpdate(true)
        function tooltip.OnFrame(self, deltaTime)
            if totalTime > delay then
                if alpha < 1 then
                    self:SetAlpha(alpha, true)
                    alpha = alpha + (deltaTime * 4)
                else
                    self:SetAlpha(1, true)
                    self:SetNeedsFrameUpdate(false)
                end
            end
            totalTime = totalTime + deltaTime
        end
    end
    
    return tooltip
end

# helpers functions to make is simple to add tooltips
--[[
function AddButtonTooltip(control, tooltipID, delay)
    local tempdelay = delay or 1
    control.HandleEvent = function(self, event)
        if event.Type == 'MouseEnter' then
            CreateMouseoverDisplay(self, tooltipID, tempdelay, true)
        elseif event.Type == 'MouseExit' then
            DestroyMouseoverDisplay()
        end
        return Button.HandleEvent(self, event)
    end
end 
]]--

function AddControlTooltip(control, tooltipID, delay)
    local oldHandleEvent = control.HandleEvent
    control.HandleEvent = function(self, event)
        if event.Type == 'MouseEnter' then
            CreateMouseoverDisplay(self, tooltipID, delay or 1, true)
        elseif event.Type == 'MouseExit' then
            DestroyMouseoverDisplay()
        end
        return oldHandleEvent(self, event)
    end
end

function AddCheckboxTooltip(control, tooltipID)
    control.HandleEvent = function(self, event)
        if event.Type == 'MouseEnter' then
            CreateMouseoverDisplay(self, tooltipID, 1, true)
        elseif event.Type == 'MouseExit' then
            DestroyMouseoverDisplay()
        end
        return Checkbox.HandleEvent(self, event)
    end
end

function AddComboTooltip(control, tooltipTable, optPosition)
    local locParent = optPosition or control
    control.OnMouseExit = function(self)
        DestroyMouseoverDisplay()
    end
    control.OnOverItem = function(self, index, text)
        #tooltip popup here, note, -1 is possible index (which means not over an item)
        if index != -1 and tooltipTable[index] then
            CreateMouseoverDisplay(locParent, tooltipTable[index], nil, true)
        else
            DestroyMouseoverDisplay()
        end
    end
end

function RemoveComboTooltip(control)
    control.OnMouseExit = function(self)
    end
    control.OnOverItem = function(self, index, text)
    end
end

function SetTooltipText(id)
    if not mouseoverDisplay then return end
    if mouseoverDisplay.title then
        mouseoverDisplay.title:SetText(id)
    else
        mouseoverDisplay:SetText(id)
    end
end